package com.example.service.impl;

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.example.entity.Post;
import com.example.mapper.PostMapper;
import com.example.service.PostService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.utils.RedisUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author 公众号：java思维导图
 * @since 2019-04-18
 */
@Slf4j
@Service
public class PostServiceImpl extends ServiceImpl<PostMapper, Post> implements PostService {

    @Autowired
    RedisUtil redisUtil;

    @Override
    public void initIndexWeekRank() {
        List<Post> last7DatePosts = this.list(new QueryWrapper<Post>()
                .ge("created", DateUtil.offsetDay(new Date(), -7).toJdkDate())
                .select("id", "title", "user_id", "comment_count", "view_count", "created"));

        for(Post post : last7DatePosts) {
            String key = "day_rank:" + DateUtil.format(post.getCreated(), DatePattern.PURE_DATE_FORMAT);

            long between = DateUtil.between(new Date(), post.getCreated(), DateUnit.DAY);

            //有效期
            long expiretime = (7 - between) * 24 * 60 * 60;

            redisUtil.zSet(key, post.getId(), post.getCommentCount());
            redisUtil.expire(key, expiretime);

            this.hashCachePostIdAndTitle(post);
        }

        this.zUnionAndStoreLast7DaysForLastWeekRank();
    }

    private void hashCachePostIdAndTitle(Post post) {
        boolean isExist = redisUtil.hasKey("rank_post_" + post.getId());
        if(!isExist) {
            long between = DateUtil.between(new Date(), post.getCreated(), DateUnit.DAY);
            long expiretime = (7 - between) * 24 * 60 * 60;

            redisUtil.hset("rank_post_" + post.getId(), "post:id", post.getId(), expiretime);
            redisUtil.hset("rank_post_" + post.getId(), "post:title", post.getTitle(), expiretime);
            redisUtil.hset("rank_post_" + post.getId(), "post:comment_count", post.getCommentCount(), expiretime);
        }
    }

    private void zUnionAndStoreLast7DaysForLastWeekRank() {
        String prefix = "day_rank:";

        String key = prefix + DateUtil.format(new Date(), DatePattern.PURE_DATE_FORMAT);

        List<String> keys = new ArrayList<>();
        for(int i = -7; i< 0; i++) {
            Date date = DateUtil.offsetDay(new Date(), i).toJdkDate();
            keys.add(prefix + DateUtil.format(date, DatePattern.PURE_DATE_FORMAT));
        }

        redisUtil.zUnionAndStore(key, keys, "last_week_rank");
    }

    @Cacheable(cacheNames = "cache_post", key = "'post_' + #id")
    @Override
    public Post get(long id) {
        log.info("-----------> 查库了");
        return this.getById(id);
    }

    @CacheEvict(cacheNames = "cache_post", allEntries = true)
    @Override
    public boolean update(Post post) {
        log.info("-----------> 删除缓存了·");
        return updateById(post);
    }

    @CacheEvict(cacheNames = "cache_post", allEntries = true)
    @Override
    public boolean delete(long id) {
        return removeById(id);
    }
}
